/**
 * 动态标签
 * @global ym2FormTag
 * @link https://www.kancloud.cn/cleverstone/ymb2
 * @copyright Copyright (c) 2020 Yii Manager Software LLC
 */

~function (global, layui) {
    "use strict";

    var $ = layui.$,
        MOD_NAME = 'tag',
        TAG_CLASS = '.ym-tag',
        BUTTON_NEW_TAG = 'ym-button-new-tag',
        INPUT_NEW_TAG = 'ym-input-new-tag',
        TAG_ITEM = 'ym-tag-item',
        CLOSE = 'ym-tag-close',
        BUTTON_REMOTE_TAG = 'ym-remote-btn',
        DEFAULT_SKIN = 'layui-btn layui-btn-sm layui-btn-theme',
        newAddTags = [],
        oldTagsDom = [],
        tabFocusInput = new Function(),
        tag = function () {
            this.config = {
                skin: DEFAULT_SKIN, tagText: '<i class="layui-font-18 layui-icon layui-icon-add-circle"></i>'
            };
            this.configs = {}
        },
        getVals = function (filter) {
            var tagElem = typeof filter == "string" ? $(TAG_CLASS + '[lay-filter=' + filter + ']') : filter;
            var result = [];
            tagElem.find('>.' + TAG_ITEM).each(function () {
                result.push($(this).attr('lay-val'));
            });
            return result;
        },
        isUnique = function (needle, haystack) {
            haystack = haystack || [];
            var index = haystack.map(function (value) {
                return value.trim();
            }).indexOf(needle.trim());
            return index === -1;
        };

    //全局设置
    tag.prototype.set = function (options) {
        var that = this;
        $.extend(true, that.config, options);
        tag.render();
        return that;
    };

    //表单事件监听
    tag.prototype.on = function (events, callback) {
        return layui.onevent.call(this, MOD_NAME, events, callback);
    };

    //外部Tag新增
    tag.prototype.add = function (filter, options) {
        var tagElem = $(TAG_CLASS + '[lay-filter=' + filter + ']');
        var result = call.add(null, tagElem, options);
        if ( false === result ) {
            return false;
        }

        call.tagAuto(filter);
        return this;
    };

    //外部Tag删除
    tag.prototype.delete = function (filter, layid) {
        var tagElem = $(TAG_CLASS + '[lay-filter=' + filter + ']'),
            tagItemElem = tagElem.find('>.' + TAG_ITEM + '[lay-id="' + layid + '"]');
        call.delete(null, tagItemElem);
        call.tagAuto(filter);
        return this;
    };

    //获取所有Tag值
    tag.prototype.values = getVals;

    //删除新增标签
    tag.prototype.removeNewAdd = function (filter) {
        var tags = newAddTags[filter] || [];
        tags.forEach(function ($ele) {
            $ele.remove();
        });
        //清空
        newAddTags[filter] = [];
        call.tagAuto(filter);
    };

    //重置dom
    tag.prototype.resetDom = function (filter) {
        var $oldTagItem = oldTagsDom[filter] || '',
            $tagElem = $(TAG_CLASS + '[lay-filter=' + filter + ']');
        if ($oldTagItem) {
            $tagElem.empty().append($oldTagItem);
            $tagElem.each(function () {
                $(this).find('.' + CLOSE).on('click', call.delete);
                if ( $tagElem.attr("lay-newTag") ) {
                    $(this).find('.' + BUTTON_NEW_TAG).on('click', call.input);
                }

                $(this).find('.' + BUTTON_REMOTE_TAG).on('click', call.remoteClick);
            });
        }
    };

    //基础事件体
    var call = {
        //remote事件
        remoteClick: function (evt) {
            var that = this;
            evt.stopPropagation();
            var parents = $(that).parents(TAG_CLASS).eq(0),
                filter = parents.attr('lay-filter');
            layui.event.call(this, MOD_NAME, 'remote(' + filter + ')', {
                elem: parents,
                othis: that,
            });
        },
        //Tag点击
        tagClick: function (e, index, tagItemElem, options) {
            options = options || {};
            var othis = tagItemElem || $(this),
                index = index || othis.index(othis),
                parents = othis.parents(TAG_CLASS).eq(0), filter = parents.attr('lay-filter');
            layui.event.call(this, MOD_NAME, 'click(' + filter + ')', {
                elem: parents, index: index
            });
        }
        //Tag新增事件
        , add: function (e, tagElem, options) {
            var filter = tagElem.attr('lay-filter'),
                buttonNewTag = tagElem.children('.' + BUTTON_NEW_TAG),
                index = buttonNewTag.index(),
                newTag = '<button lay-id="' + (options.id || '') + '" lay-val="' + (options.text || '') + '"' + (options.attr ? ' lay-attr="' + options.attr + '"' : '') + ' type="button" class="' + TAG_ITEM + '">' + (options.text || '') + '</button>',
                $newTag = $(newTag),
                tagVals = getVals(tagElem);
            if (!isUnique(options.text, tagVals)) {
                alert('[ ' + options.text + ' ]重复');
                return false;
            }

            var result = layui.event.call(this, MOD_NAME, 'add(' + filter + ')', {
                elem: tagElem, index: index, othis: $newTag
            });

            if (result === false) return false;
            buttonNewTag[0] ? buttonNewTag.before($newTag) : tagElem.append($newTag);

            newAddTags[filter] = newAddTags[filter] || [];
            newAddTags[filter].push($newTag);

            return true;
        }
        //Tag输入事件
        , input: function (e, othis) {
            var buttonNewTag = othis || $(this),
                parents = buttonNewTag.parents(TAG_CLASS).eq(0),
                filter = parents.attr('lay-filter'),
                options = tag.configs[filter] = $.extend({}, tag.config, tag.configs[filter] || {}, options);
            //标签输入框
            var inpatNewTag = $('<div class="' + INPUT_NEW_TAG + '"><input type="text" autocomplete="off" class="layui-input"></div>');
            inpatNewTag.addClass(options.skin);
            buttonNewTag.after(inpatNewTag).remove();
            inpatNewTag.children('.layui-input').on('blur', function () {
                if (this.value.trim()) {
                    var options = {
                        text: this.value.trim()
                    }
                    call.add(null, parents, options);
                }

                inpatNewTag.remove();
                call.tagAuto(filter);
                tabFocusInput = function () {
                    $(this).children('.' + BUTTON_NEW_TAG).click();
                };
            }).focus();
        }
        //Tag删除
        , delete: function (e, othis) {
            var tagItem = othis || $(this).parent(),
                index = tagItem.index(),
                parents = tagItem.parents(TAG_CLASS).eq(0),
                filter = parents.attr('lay-filter');

            var result = layui.event.call(this, MOD_NAME, 'delete(' + filter + ')', {
                elem: parents, index: index
            });
            if (result === false) return;
            tagItem.remove();
            call.tagAuto(filter);
        }
        //Tag 自适应
        , tagAuto: function (filter) {
            filter = filter || '';
            var options = filter ? tag.configs[filter] || tag.config : tag.config;
            var elemFilter = function () {
                return filter ? ('[lay-filter="' + filter + '"]') : '';
            }();
            var $tagParents = $(TAG_CLASS + elemFilter);
            $tagParents.each(function () {
                var othis = $(this),
                    allowMin = othis.attr('lay-mincount') || 0,
                    allowMax = othis.attr('lay-maxcount') || 99999,
                    isAllowClose = othis.attr('lay-allowClose'),
                    isAllowNewAdd = othis.attr('lay-newTag'),
                    isAllowRemote = othis.attr('lay-remote'),
                    tagItem = othis.children('.' + TAG_ITEM),
                    buttonNewTag = othis.children('.' + BUTTON_NEW_TAG),
                    buttonRemote = othis.children('.' + BUTTON_REMOTE_TAG);

                tagItem.removeClass( DEFAULT_SKIN ).addClass( options.skin );

                //允许关闭
                if (isAllowClose && tagItem.length > allowMin) {
                    tagItem.each(function () {
                        var li = $(this);
                        if (!li.find('.' + CLOSE)[0]) {
                            var close = $('<i class="layui-icon layui-unselect ' + CLOSE + '">&#x1006;</i>');
                            close.on('click', call.delete);
                            li.append(close);
                        }
                    });
                }

                //移除关闭按钮
                if (isAllowClose && tagItem.length > 0 && tagItem.length <= allowMin) {
                    tagItem.each(function () {
                        var li = $(this);
                        li.find('.' + CLOSE).remove();
                    });
                }

                //允许新增标签
                if (isAllowNewAdd && buttonNewTag.length === 0 && tagItem.length < allowMax) {
                    buttonNewTag = $('<button type="button" class="' + BUTTON_NEW_TAG + ' layui-btn layui-btn-sm layui-btn-primary"></button>');
                    buttonNewTag.on('click', call.input);
                    othis.append(buttonNewTag);
                    buttonNewTag.html(options.tagText);
                }

                //允许远程添加
                if (isAllowRemote && buttonRemote.length === 0 && tagItem.length < allowMax) {
                    if ( buttonNewTag.length === 0 ) {
                        buttonNewTag = $('<button type="button" class="' + BUTTON_NEW_TAG + ' layui-btn layui-btn-sm layui-btn-primary" style="padding:0;"></button>');
                        othis.append(buttonNewTag);
                    }

                    var remoteBtn = $('<button type="button" class="' + BUTTON_REMOTE_TAG + ' layui-btn layui-btn-sm layui-btn-primary"><i class="layui-icon">&#xe615;</i></button>');
                    remoteBtn.on('click', call.remoteClick);
                    buttonNewTag.append(remoteBtn);
                }

                //移除新增标签
                if ( buttonNewTag.length > 0 &&  tagItem.length >= allowMax ) {
                    buttonNewTag.remove();
                }

            });

            return $tagParents;
        }
    };

    tag.prototype.init = function (filter, options) {
        if (filter) {
            tag.configs[filter] = $.extend({}, tag.config, tag.configs[filter] || {}, options);
        }
        var $tagParents = call.tagAuto.call(this, filter);
        $tagParents.each(function () {
            var othis = $(this),
                thisFilter = othis.attr('lay-filter') || '';
            if (thisFilter) {
                oldTagsDom[thisFilter] = othis.html();
            }
        });
        return $tagParents;
    };

    tag.prototype.render = tag.prototype.init;
    var tag = new tag(),
        dom = $(document);

    tag.render();

    //监听tab事件，快速聚焦输入框。
    dom.on("keydown", TAG_CLASS, function (evt) {
        if (evt.keyCode !== 0x09) return;
        var that = this;
        //因为blur在下一个宏中，所以把keydown回调放到下一个宏中。
        global.setTimeout(function () {
            tabFocusInput.apply(that);
        });
    });
    dom.on('click', '.' + TAG_ITEM, call.tagClick); //tag 单击事件

    layui.ym2FormTag = global.ym2FormTag = tag;

}(window, layui);